package ldh.maker.component;

import com.jfoenix.controls.JFXTabPane;
import javafx.application.Platform;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.collections.transformation.FilteredList;
import javafx.concurrent.Task;
import javafx.geometry.Insets;
import javafx.geometry.Orientation;
import javafx.geometry.Side;
import javafx.scene.control.*;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.util.Callback;
import ldh.database.Table;
import ldh.maker.code.CreateCode;
import ldh.maker.database.TableInfo;
import ldh.maker.db.EnumDb;
import ldh.maker.db.PojoDb;
import ldh.maker.db.SettingDb;
import ldh.maker.db.TableNoDb;
import ldh.maker.util.*;
import ldh.maker.vo.SettingData;
import ldh.maker.vo.TableNo;
import ldh.maker.vo.TreeNode;

import java.sql.SQLException;
import java.util.List;
import java.util.Map;

public class TableUi extends ContentUi {

    private VBox tableList;
    private TextField filterText;
    private ListView<Table> tableNamesList;
    private Button createAllCodeBtn = new Button("一键生成代码");

    private ObservableList<Table> tableValueList = FXCollections.observableArrayList();
    private FilteredList<Table> filteredData = new FilteredList<>(tableValueList, p -> true);

    private JFXTabPane tabPane;
    private SplitPane splitPane;
    private JFXTabPane contentPane;
//    protected SettingPane settingPane;

    public TableUi() {
        createAllCodeBtn.getStyleClass().add("btn");
        createAllCodeBtn.getStyleClass().add("btn-primary");
    }

    public void setTreeItem(TreeItem<TreeNode> treeItem) {
        this.treeItem = treeItem;
        splitPane = new SplitPane();
        splitPane.setOrientation(Orientation.HORIZONTAL);
        splitPane.setDividerPositions(0.4d);

        init();

        tabPane = new JFXTabPane();
        tabPane.setSide(Side.LEFT);
        Tab settingTab = new Tab("设置");
        settingTab.setClosable(false);
        TabPane settingPane = buildSettingPane(treeItem, treeItem.getValue().getData().toString());
        settingTab.setContent(settingPane);

        Tab coreTab = new Tab("主面板");
        coreTab.setClosable(false);
        coreTab.setContent(splitPane);

        tabPane.getTabs().addAll(settingTab, coreTab);
        tableList.setMaxWidth(200);
        this.setCenter(tabPane);

        if ((settingPane instanceof SettingPane) && ((SettingPane)settingPane).isSetting()) {
            tabPane.getSelectionModel().select(coreTab);
        }
    }

    private void init() {
        String db = treeItem.getValue().getData().toString();
        TableInfo tableInfo = DbInfoFactory.getInstance().get(treeItem.getValue().getParent().getId() + "_" + db);
        tableValueList.addAll(tableInfo.getTables().values());

        tableList = new VBox();
        filterText = new TextField("过滤");
        tableNamesList = new ListView<>();
        initListEvent();

        tableNamesList.setCellFactory(new Callback<ListView<Table>, ListCell<Table>>(){

            @Override
            public ListCell<Table> call(ListView<Table> param) {
                return new ListCell<Table>() {
                    @Override
                    public void updateItem(Table item, boolean empty) {
                        super.updateItem(item, empty);
                        Label label = new Label();
                        if (item != null) {
                            label.setText(item.getName());
                            if (item.getColumnList() != null && item.getPrimaryKey() == null) {
                                label.setStyle("-fx-background-color: red");
                            }
                            setGraphic(label);
                        } else {
                            setText(null);
                            setGraphic(null);
                        }
                    }
                };
            }
        });
        VBox.setVgrow(tableNamesList, Priority.ALWAYS);

        tableList.getChildren().addAll(filterText, tableNamesList, createAllCodeBtn);
        tableList.setSpacing(2d);
        tableList.setPadding(new Insets(5, 5, 2, 5));

        contentPane = new JFXTabPane();
        contentPane.setTabClosingPolicy(TabPane.TabClosingPolicy.ALL_TABS);
        splitPane.getItems().addAll(tableList, contentPane);

        createAllCodeBtn.setPrefWidth(200);
        tableNamesList.setItems(filteredData);
    }

    private void initListEvent() {
        tableNamesList.setOnMouseClicked((e)->{
            if (e.getClickCount() != 2) return;
            String selectTable = tableNamesList.getSelectionModel().getSelectedItem().getName();
            Tab tab = getTab(selectTable);
            if (tab != null) {
                contentPane.getSelectionModel().select(tab);
                return;
            }
            tab = createContentTab(selectTable);
            contentPane.getTabs().add(tab);
            contentPane.getSelectionModel().select(tab);

            String db = treeItem.getValue().getData().toString();
            Table table = DbInfoFactory.getInstance().get(treeItem.getValue().getParent().getId() + "_" + db).getTable(selectTable);
            if (table.getPrimaryKey() == null) {
                DialogUtil.show(Alert.AlertType.CONFIRMATION, "提示信息", "没有主键");
                reloadData();
            }
        } );

        filterText.textProperty().addListener((observable, oldValue, newValue) -> {
            filteredData.setPredicate(table -> {
                if (newValue == null || newValue.isEmpty()) {
                    return true;
                }
                System.out.println("newValue:" + newValue + ", tableName:" + table.getName() + ", size:" + filteredData.size());
                String lowerCaseFilter = newValue.toLowerCase();
                if (lowerCaseFilter.equals("过滤") || lowerCaseFilter.trim().equals("")) return true;
                if (table.getName().startsWith(lowerCaseFilter)) {
                    return true;
                }
                return false; // Does not match.
            });
        });

        filterText.setOnMouseEntered(e->{
            if (filterText.getText().equals("过滤")) {
                filterText.setText("");
            }
        });

        createAllCodeBtn.setOnAction(e->{
            saveAllData();
        });
    }

    private void reloadData() {
        tableValueList.clear();
        String db = treeItem.getValue().getData().toString();
        TableInfo tableInfo = DbInfoFactory.getInstance().get(treeItem.getValue().getParent().getId() + "_" + db);
        for (Table table : tableInfo.getTables().values()) {
            tableValueList.add(table);
        }
    }

    private Tab getTab(String selectTable) {
        for (Tab c : contentPane.getTabs()) {
            if (c.getText().equals(selectTable)) {
                return c;
            }
        }
        return null;
    }

    protected Tab createContentTab(String selectTable) {
        Tab tab = new Tab();
        tab.setText(selectTable);
        String db = treeItem.getValue().getData().toString();
        CodeUi codeUi = new CodeUi(treeItem, db, selectTable);
        tab.setContent(codeUi);
        return tab;
    }

    public TabPane getTabPane() {
        return contentPane;
    }

    public void saveAllData() {
        getTabPane().getTabs().clear();
        String dbName = treeItem.getValue().getData().toString();
        TableInfo tableInfo = DbInfoFactory.getInstance().get(treeItem.getValue().getParent().getId() + "_" + dbName);

        isSetting(dbName);

        Task<Void> task = new Task<Void>() {
            @Override protected Void call() throws Exception {
                int i=0;
                int size = tableInfo.getTables().size();
                for(Map.Entry<String, Table> entry : tableInfo.getTables().entrySet()) {
                    i++;
                    Table table = entry.getValue();
                    try {
                        Map<String, Boolean> funs = MakerConfig.getInstance().getFunctionMap(table.getName());
                        if (funs == null || funs.size() == 0) {
                            funs = FreeMakerUtil.getAllFunction(table);
                            MakerConfig.getInstance().addFunctionMap(table.getName(), funs);
                        }
                        updateMessage("加载表第" + i + "数据， 总" + size);
                        boolean isLoad = PojoDb.loadData(treeItem.getValue().getParent(), dbName, table);
                        if (!isLoad && table.getPrimaryKey() != null && !table.getPrimaryKey().isComposite()) {
                            PojoDb.saveOrUpdate(dbName, table, treeItem.getValue().getParent().getId());
                        }

                    } catch (Exception e1) {
                        e1.printStackTrace();
                    }
                }
                EnumDb.loadData(treeItem.getValue().getParent().getId(), dbName);
                updateMessage("开始生成代码");

                TableNo tableNo = TableNoDb.loadData(treeItem.getValue().getParent(), dbName);
                if (tableNo != null) {
                    List<String> tableNoes = tableNo.getTableNoes();
                    for (String tableName : tableNoes) {
                        if (tableInfo.getTable(tableName) != null)
                        tableInfo.getTable(tableName).setCreate(false);
                    }
                }

                i=0;
                CreateCode.isCreate = true;
                for(Map.Entry<String, Table> entry : tableInfo.getTables().entrySet()) {
                    i++;
                    Table table = entry.getValue();
                    if (table.getPrimaryKey() == null || !table.isCreate()) {
                        updateMessage("开始生成第" + i + "个代码， 总" + size);
                        continue;
                    }
                    try {
//                        if (size < 100) {
//                            Tab tab = createContentTab(table.getName());
//                            CodeUi codeUi = (CodeUi) tab.getContent();
//                            Platform.runLater(()->{
//                                contentPane.getTabs().add(tab);
//                                contentPane.getSelectionModel().select(tab);
//                            });
//                            Thread.sleep(50);
//                            updateMessage("开始生成第" + i + "个代码， 总" + size);
//                            updateProgress(i, tableInfo.getTables().size());
//                            codeUi.createCode(table, true);
//                            Thread.sleep(200);
//                        } else {
//
//                        }
                        SettingData data = SettingDb.loadData(treeItem.getValue().getParent(), dbName);
//                            CreateCode createCode = new CreateCode(data, treeItem, dbName, table);
                        CreateCode createCode = buildCreateCode(data, treeItem, dbName, table);
                        updateMessage("开始生成第" + i + "个代码， 总" + size);
                        updateProgress(i, tableInfo.getTables().size());
                        createCode.create();
                        Thread.sleep(200);
                    } catch (Exception e1) {
                        e1.printStackTrace();
                    }
                }

                updateProgress(tableInfo.getTables().size(), tableInfo.getTables().size());
                done();
                return null;
            }
        };

        UiUtil.STATUSBAR.textProperty().bind(task.messageProperty());
        UiUtil.STATUSBAR.progressProperty().bind(task.progressProperty());

        // remove bindings again
        task.setOnSucceeded(event -> {
            UiUtil.STATUSBAR.textProperty().unbind();
            UiUtil.STATUSBAR.progressProperty().unbind();
            Platform.runLater(()->{
                DialogUtil.show(Alert.AlertType.INFORMATION, "代码生成完成", "代码生成完成");
            });
        });

        new Thread(task).start();

    }

    protected  CreateCode buildCreateCode(SettingData data, TreeItem<TreeNode> treeItem, String dbName, Table table) {
        return new CreateCode(data, treeItem, dbName, table);
    }

    protected TabPane buildSettingPane(TreeItem<TreeNode> treeItem, String dbName) {
        return new SettingPane(treeItem, dbName);
    }

    protected boolean isSetting(String dbName) {
        try {
            SettingData data = SettingDb.loadData(treeItem.getParent().getValue(), dbName);
            if (data == null) {
                DialogUtil.show(Alert.AlertType.ERROR, "错误操作", "请设置项目的包路径");
                return false;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return true;
    }
}
